package com.acme.bankapp.domain.accounting;

import java.io.Serializable;


abstract class AbstractAccount implements Account, Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -6634808192500043237L;

	public static final double DEFAULT_INITIAL_BALANCE = 0;

	protected double balance;
	
	/**
	 * Global account id. 
	 * Use to identify account.
	 */
	private final long accountId;


	public long getAccountId() {
		return accountId;
	}

	/**
	 * common constructor
	 * 
	 * @param balance
	 *            Initial balance
	 */
	public AbstractAccount(long id,double balance) {
		accountId = id;
		if (balance < 0)
			throw new IllegalArgumentException("balance cannot be less then 0");
		this.balance = balance;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public double getBalance() {
		return balance;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void deposit(double x) {
		balance += x;

	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public abstract void withdraw(double x) throws NotEnoughFundsException;

	/**
	 * {@inheritDoc}
	 */
	@Override
	public abstract double maximumAmountToWithdraw();

	@Override
	public String toString() {
		return new StringBuilder().append(this.getClass().getSimpleName())
				.append(" : ").append(accountId).append(",balance: ").append(this.getBalance())
				.append(" max wihdraw: ")
				.append(this.maximumAmountToWithdraw()).append("\n").toString();
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + new Long(accountId).hashCode();
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AbstractAccount other = (AbstractAccount) obj;
		return this.accountId == other.accountId;
	}

}
